.TITLE CTDRV .IDENT /08/ ; ; Copyright (c) 1995-1999 by Mentec, Inc., U.S.A. ; All rights reserved ; ; THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY ONLY BE USED ; OR COPIED IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE. ; ; VERSION 08 ; ; D. N. CUTLER 13-MAR-74 ; ; PREVIOUSLY MODIFIED BY: ; ; P. J. BEZEREDI ; D. N. CUTLER ; C. A. D'ELIA ; B. LYONS ; ; MODIFIED BY: ; ; P. J. BEZEREDI 05-JUL-78 ; ; PB079 -- INSURE R2 CONTAINS CSR ADDRESS BEFORE LOGGING ; AN ERROR. ; ; P. J. BEZEREDI 18-JUL-78 ; ; PB081 -- EXPAND I/O ACTIVITY IMFORMATION REPORTED AT ; TIME OF AN ERROR. ; ; TA11 TAPE CASSETTE CONTROLLER DRIVER ; ; NOTE: THIS IS A MINIMAL DRIVER AND CONTAINS NO ERROR RECOVERY. ; ; MACRO LIBRARY CALLS ; .MCALL HWDDF$,PKTDF$ HWDDF$ ;DEFINE HARDWARE REGISTERS PKTDF$ ;DEFINE I/O PACKET OFFSETS ; ; ERROR PROCESSING CONTROL TABLE ; ERRTB: .BYTE IE.DNR&377,1000/400 ;DEVICE NOT READY .BYTE IE.WLK&377,10000/400 ;DRIVE WRITE LOCKED .BYTE IE.EOT&377,20000/400 ;END OF TAPE .BYTE IE.EOF&377,4000/400 ;END OF FILE .BYTE IE.DAO&377,2000/400 ;DATA OVERRUN .BYTE IE.VER&377,377 ;BLOCK CHECK ERROR ; ; LEGAL FUNCTION DISPATCH TABLE ; LGFCN: .WORD IO.RLB ;READ LOGICAL BLOCK .BYTE 105,10. ; .WORD RDBLK ; .WORD IO.WLB ;WRITE LOGICAL BLOCK .BYTE 103,10. ; .WORD WRBLK ; .WORD IO.EOF ;WRITE END OF FILE .BYTE 101,10. ; .WORD WREOF ; .WORD IO.RWD ;REWIND .BYTE 117,34. ; .WORD WREOF ; .WORD IO.SPB ;SPACE BLOCK .BYTE 115,128. ; .WORD SPCBK ; .WORD IO.SPF ;SPACE FILE .BYTE 113,128. ; .WORD SPCBK ; ; ; DRIVER DISPATCH TABLE ; DDT$ CT,T$$A11 ;GENERATE DISPATCH TABLE ;+ ; **-CTINI-TA11 TAPE CASSETTE CONTROLLER INITIATOR ; ; THIS ROUTINE IS ENTERED FROM THE QUEUE I/O DIRECTIVE WHEN AN I/O REQUE ; IS QUEUED AND AT THE END OF A PREVIOUS I/O OPERATION TO PROPAGATE THE ; TION OF THE DRIVER. IF THE SPECIFIED CONTROLLER IS NOT BUSY, THEN AN A ; IS MADE TO DEQUEUE THE NEXT I/O REQUEST. ELSE A RETURN TO THE CALLER I ; EXECUTED. IF THE DEQUEUE ATTEMPT IS SUCCESSFUL, THEN THE NEXT I/O OPER ; ATION IS INITIATED. A RETURN TO THE CALLER IS THEN EXECUTED. ; ; INPUTS: ; ; R5=ADDRESS OF THE UCB OF THE CONTROLLER TO BE INITIATED. ; ; OUTPUTS: ; ; IF THE SPECIFIED CONTROLLER IS NOT BUSY AND AN I/O REQUEST IS WA ; ING TO BE PROCESSED, THEN THE REQUEST IS DEQUEUED AND THE I/O OP ; ATION IS INITIATED. ;- .ENABL LSB CTINI: GTPKT$ CT,T$$A11,CTPWF ;GET NEXT I/O PACKET TO PROCESS ; ; THE FOLLOWING ARGUMENTS ARE RETURNED BY $GTPKT: ; ; R1=ADDRESS OF THE I/O REQUEST PACKET. ; R2=PHYSICAL UNIT NUMBER OF THE REQUEST UCB. ; R3=CONTROLLER INDEX. ; R4=ADDRESS OF THE STATUS CONTROL BLOCK. ; R5=ADDRESS OF THE UCB OF THE CONTROLLER TO BE INITIATED. ; ; TA11 TAPE CASSETTE FUNCTION INDEPENDENT I/O REQUEST PACKET FORMAT: ; ; WD. 00 -- I/O QUEUE THREAD WORD. ; WD. 01 -- REQUEST PRIORITY, EVENT FLAG NUMBER. ; WD. 02 -- ADDRESS OF THE TCB OF THE REQUESTOR TASK. ; WD. 03 -- POINTER TO SECOND LUN WORD IN REQUESTOR TASK HEADER. ; WD. 04 -- CONTENTS OF THE FIRST LUN WORD IN REQUESTOR TASK HEADE ; WD. 05 -- I/O FUNCTION CODE (IO. RLB 1 IO.RWD/IO.SPB/IO.SPF/IO.E ; WD. 06 -- VIRTUAL ADDRESS OF I/O STATUS BLOCK. ; WD. 07 -- RELOCATION BIAS OF I/O STATUS BLOCK. ; WD. 10 -- I/O STATUS BLOCK ADDRESS (REAL OR DISPLACEMENT + 14000 ; WD. 11 -- VIRTUAL ADDRESS OF AST SERVICE ROUTINE. ; MOV #LGFCN,R3 ;POINT TO LEGAL FUNCTION TABLE MOV #6,R0 ;SET NUMBER OF ENTRIES IN TABLE 10$: CMP I.FCN(R1),(R3)+ ;FUNCTION CODE MATCH? BEQ 20$ ;IF EQ YES CMP (R3)+,(R3)+ ;POINT TO NEXT TABLE ENTRY DEC R0 ;ANY MORE TABLE ENTRIES? BGT 10$ ;IF GT YES MOV #IE.IFC&377,R0 ;SET ILLEGAL FUNCTION STATUS BR 50$ ;FINISH IN COMMON CODE ; ; FUNCTION CODE MATCH FOUND ; 20$: SWAB R2 ;SWAP UNIT NUMBER TO LEFT BYTE BISB (R3)+,R2 ;MERGE FUNCTION CODE WITH UNIT MOVB (R3)+,S.ITM(R4) ;SPACING FUNCTION? BPL 30$ ;IF PL NO ; ; SPACING FUNCTION DEPENDENT I/O PACKET FORMAT: ; ; WD. 12 -- SPACING COUNT (POSITIVE=FORWARD, NEGATIVE=BACKWARD). ; WD. 13 -- NOT USED. ; WD. 14 -- NOT USED. ; WD. 15 -- NOT USED. ; WD. 16 -- NOT USED. ; WD. 17 -- NOT USED. ; WD. 20 -- NOT USED. ; BISB #S3.SIP,S.ST3(R4) ;SET POSITIONING IN PROGRESS MOV U.BUF(R5),I.PRM+4(R1) ;MOVE SPACING COUNT TO COMMON PLAC MOV U.BUF(R5),U.CNT(R5) ;MOVE SPACING COUNT TO COMMON PLACE BEQ 40$ ;IF EQ NO SPACING REQUIRED BPL 30$ ;IF PL SPACE FORWARD NEG U.CNT(R5) ;CONVERT TO POSITIVE COUNT NEG I.PRM+4(R1) ;CONVERT TO POSITIVE COUNT SUB #4,R2 ;CONVERT TO REVERSE FUNCTION ; ; READ/WRITE LOGICAL FUNCTION DEPENDENT I/O PACKET FORMAT: ; ; WD. 12 -- RELOCATION BIAS OF DATA BUFFER. ; WD. 13 -- DATA BUFFER ADDRESS. ; WD. 14 -- NUMBER OF BYTES TO BE TRANSFERED. ; WD. 15 -- NOT USED. ; WD. 16 -- NOT USED. ; WD. 17 -- NOT USED. ; WD. 20 -- NOT USED. ; ; NO FUNCTION DEPENDENT PARAMETERS ARE REQUIRED FOR REWIND AND WRITE EOF ; 30$: MOVB S.ITM(R4),S.CTM(R4) ;SET CURRENT DEVICE TIMEOUT COUNT MOV (R3),U.CW2(R5) ;SET INITIAL INTERRUPT ADDRESS CALL $BMSET ;SET I/O ACTIVE IN BIT MAP MOV R2,@S.CSR(R4) ;INITIATE FUNCTION ; ; CANCEL I/O OPERATION IS A NOP FOR TA11 TAPE CASSETTES. ; CTCAN: ;REF LABEL ; ; POWERFAIL IS HANDLED VIA THE DEVICE TIMEOUT FACILITY AND THEREFORE CAU ; NO IMMEDIATE ACTION ON THE DEVICE. THIS IS DONE TO AVOID A RACE CONDIT ; THAT COULD EXIST IN RESTARTING THE I/O OPERATION. ; CTPWF: RETURN ; ; ; NO SPACING REQUIRED ; 40$: MOV #IS.SUC&377,R0 ;SET SUCCESSFUL COMPLETION STATUS 50$: BR 110$ ; ;+ ; **-$CTINT-TA11 TAPE CASSETTE CONTROLLER INTERRUPTS ;- INTSE$ CT,PR6,T$$A11 ;;;GENERATE INTERRUPT SAVE CODE MOV R3,-(SP) ;;;SAVE R3 MOV U.SCB(R5),R4 ;;;GET ADDRESS OF SCB MOVB S.ITM(R4),S.CTM(R4) ;;;RESET CURRENT DEVICE TIMEOUT COUN MOV S.CSR(R4),R3 ;;;GET ADDRESS OF CSR BIT #200,(R3)+ ;;;TRANSFER REQUEST? BNE 60$ ;;;IF NE YES MOV -2(R3),U.CW3(R5) ;;;SAVE CURRENT STATUS 60$: CALL @U.CW2(R5) ;;;CALL INTERRUPT ROUTINE BIS #S2.ACT,S.ST2(R4) ;;;SET I/O ACTIVE FLAG MOV (SP)+,U.CW2(R5) ;;;SAVE INTERRUPT RETURN ADDRESS MOV (SP)+,R3 ;;;RESTORE R3 JMP $INTXT ;;;EXIT FROM INTERRUPT ; ; SPACING FUNCTION (FILE AND BLOCK) ; SPCBK: BMI 70$ ;;;IF MI ERROR DEC U.CNT(R5) ;;;DECREMENT SPACING COUNT BLE 70$ ;;;IF LE DONE INC -(R3) ;;;INITIATE NEXT OPERATION CALL @(SP)+ ;;;SET INTERRUPT RETURN ADDRESS BR SPCBK ;;;GO AGAIN 70$: CLR -(R3) ;;;CLEAR INTERRUPT ENABLE TST (SP)+ ;;;REMOVE RETURN FROM STACK MOV (SP)+,R3 ;;;RESTORE R3 CALL $FORK ;;;CREATE A SYSTEM PROCESS MOV U.CW3(R5),R1 ;GET FINAL STATUS BPL 90$ ;IF PL SUCCESS BICB #^C<7*2>,R1 ;CLEAR ALL BUT FUNCTION CODE CMPB #5*2,R1 ;FORWARD OR REVERSE FUNCTION? BLE 100$ ;IF LE FORWARD BIC #120777,R1 ;CLEAR ERROR, BOT, UNIT, AND FUNCTION BEQ 40$ ;IF EQ NO ERRORS BR 100$ ;ANALYZE ERROR ; ; READ LOGICAL FUNCTION ; RDBLK: BMI WREOF ;;;IF MI ERROR DEC U.CNT(R5) ;;;DECREMENT BYTE COUNT BLT 80$ ;;;IF LT NO MORE TO READ MOV (R3),-(SP) ;;;READ BYTE FROM DATA REGISTER CALL $PTBYT ;;;PUT BYTE IN USER BUFFER CALL @(SP)+ ;;;SET INTERRUPT RETURN ADDRESS BR RDBLK ;;;GO AGAIN ; ; WRITE LOGICAL FUNCTION ; WRBLK: BMI WREOF ;;;IF MI ERROR DEC U.CNT(R5) ;;;DECREMENT BYTE COUNT BLT 80$ ;;;IF LT NO MORE TO WRITE CALL $GTBYT ;;;GET BYTE FROM USER BUFFER MOVB (SP)+,(R3) ;;;WRITE BYTE INTO DATA REGISTER CALL @(SP)+ ;;;SET INTERRUPT RETURN ADDRESS BR WRBLK ;;;GO AGAIN 80$: INC U.CNT(R5) ;;;ADJUST BYTE COUNT BIS #20,-(R3) ;;;INITIATE LAST BYTE SEQUENCE CALL @(SP)+ ;;;SET INTERRUPT RETURN ADDRESS ; ; REWIND AND WRITE END OF FILE FUNCTIONS ; WREOF: CLR -(R3) ;;;CLEAR INTERRUPT ENABLE TST (SP)+ ;;;REMOVE RETURN FROM STACK MOV (SP)+,R3 ;;;RESTORE R3 CALL $FORK ;;;CREATE A SYSTEM PROCESS 90$: MOV #IS.SUC&377,R0 ;ASSUME SUCCESSFUL COMPLETION STATUS MOV U.CW3(R5),R1 ;GET FINAL STATUS BPL 110$ ;IF PL SUCCESS 100$: SWAB R1 ;SWAP ERROR BITS TO LOW BYTE MOV #ERRTB,R2 ;GET ADDRESS OF ERROR CONTROL TABLE 105$: CLR R0 ;PICKUP NEXT ERROR STATUS CODE BISB (R2)+,R0 ; BITB (R2)+,R1 ;ERROR BIT SET? BEQ 105$ ;IF EQ NO BITB #26,R1 ;WRITE LOCK, TIMING OR OFF-LINE? BEQ 110$ ;IF EQ NO MOV S.CSR(R4),R2 ;RETREIVE CSR ADDRESS CALL $DVERR ;LOG DEVICE ERROR BR 110$ ;FINISH I/O ; ; DEVICE TIMEOUT RESULTS IN THE CURRENT OPERATION BEING TERMINATED. TIME ; USUALLY CAUSED BY POWERFAILURE BUT ALSO MAY BE THE RESULT OF A HARD- ; WARE FAILURE. ; CTOUT: CALL $DTOER ;;;LOG DEVICE TIMEOUT 110$: MOV S.PKT(R4),R1 ;RETRIEVE ADDRESS OF I/O PACKET BICB #S3.SIP,S.ST3(R4) ;RESET POSITIONING IN PROGRESS MOV I.PRM+4(R1),R1 ;GET ORIGINAL COUNT VALUE SUB U.CNT(R5),R1 ;SUBTRACT COUNT REMAINING MOV #401,R2 ;SET CURRENT AND FINAL RETRY COUNT=1 CALL $IODON ;FINISH I/O OPERATION JMP CTINI ;GO AGAIN .DSABL LSB .END